package com.fw.application.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayUserCertdocCertverifyConsultResponse;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fw.annotation.PrintParam;
import com.fw.application.controller.base.BaseController;
import com.fw.application.controller.v2.shop.read.V2ReadPackageController;
import com.fw.common.AliComm;
import com.fw.common.IdXD;
import com.fw.constant.Constant;
import com.fw.enums.AliPayEnum;
import com.fw.enums.CodeStatus;
import com.fw.enums.LogsModelEnum;
import com.fw.enums.LogsTypeEnum;
import com.fw.mes.AliAppUserAccToken;
import com.fw.mes.AliAppUserInfo;
import com.fw.mes.Result;
import com.fw.system.comm.service.DistrictService;
import com.fw.system.web.model.entity.*;
import com.fw.system.web.model.form.*;
import com.fw.system.web.model.vo.*;
import com.fw.system.web.service.*;
import com.fw.utils.AuthUtils;
import com.fw.utils.ChuangLanSmsUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.fw.mes.ResultUtils.success;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author
 * @since 2021-05-10
 */
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
@Api(tags = "用户相关")
public class FwUserController implements BaseController {

    private final IdXD idXD;
    private final IFwUcjoinService ucjoinService;
    private final IFwUsjoinService usjoinService;
    private final IFwUljoinService uljoinService;
    private final IFwMoneysService moneysService;
    private final IFwUserService userService;
    private final RedisTemplate redisTemplate;
    private final AuthUtils authUtils;
    private final IFwRuleDatasService ruleDatasService;
    private final IFwLogsService logsService;
    private final IFwIdentityService identityService;
    private final IFwAgentRegionService agentRegionService;
    private final DistrictService districtService;
    private final AliComm aliComm;
    private final IFwAddrsService addrsService;

    /**
     * 测试登陆
     */
    @GetMapping("/testLogin")
    @ApiOperation("shlo:测试登录")
    public Result testLogin() {
        FwUser user = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getId, "1400632538900258817"));
        String json = JSON.toJSON(user).toString();
        String token = authUtils.createJWT(user.getId(), json, null);
        return success(token);
    }

    /**
     * 管理员查询用户列表
     *
     * @param fwUser
     * @return
     */
    @GetMapping("/listUsers")
    @ApiOperation("shlo:管理员查询用户列表")
    public Result listUsers(@RequestParam FwUser fwUser) {
        FwUser user = getUser();
        //判断用户是管理员才可以查询相应的数据或者注解加接口权限设置
        List<FwUser> list = userService.list(Wrappers.lambdaQuery(fwUser));
        return success(list);
    }

    /**
     * shlo:手机号验证码登录
     *
     * @param phone
     * @return
     */
    @GetMapping("/Login/{phone}/{imei}/{code}")
    @ApiOperation("shlo:手机号验证码登录")
    public Result phoneLogin(@PathVariable String phone, @PathVariable String imei, @PathVariable String code) {
        //验证验证码
        Integer flag = userService.checkCode(phone, code);
        if (flag == -1) {
            return new Result().fail(0, "请去获取验证码");
        }
        if (flag == 0) {
            return new Result().fail(0, "验证码错误");
        }
        FwUser user = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getPhone, phone));
        if (user == null) {
            return new Result().fail(102, "该手机号尚未注册,请注册后登陆");
        }
        if (user.getImei() != null && !imei.equals(user.getImei())) {
            return success("-999");
        }
        if (user.getImei() == null) {
            user.setImei(imei);
            userService.updateFwUser(user);
        }
        //更新登录时间
        user.setUpdateTime(LocalDateTime.now());
        userService.updateFwUser(user);
        String json = JSON.toJSON(user).toString();
        String token = authUtils.createJWT(user.getId(), json, null);
        return success(token);
    }

    /**
     * shlo:
     * 用户手机号登录密码
     */
    @PostMapping("/loginPhone/{phone}/{passWord}/{imei}")
    @ApiOperation("shlo:用户手机号密码登录")
    @Transactional(rollbackFor = Exception.class)
    public Result loginPhone(@PathVariable String phone, @PathVariable String passWord, @PathVariable String imei) {
        //获取登录用户数据
        FwUser user = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getPhone, phone));
        //判断该手机号是否已注册
        if (user == null) {
            return new Result().fail(0, "该手机号尚未注册,请注册后登陆");
        }
        //判断手机号与密码是否匹配
        if (!user.getPassWord().equals(passWord)) {
            return new Result().fail(0, "手机号或密码错误,请核实");
        }
        if (user.getImei() != null && !imei.equals(user.getImei())) {
            return success(-999);
        }
        if (user.getImei() == null) {
            user.setImei(imei);
            userService.updateFwUser(user);
        }
        //更新登录时间
        user.setUpdateTime(LocalDateTime.now());
        userService.updateFwUser(user);
        //送回token
        String json = JSON.toJSON(user).toString();
        String token = authUtils.createJWT(user.getId(), json, null);
        return success(token);
    }

    /**
     * shlo:
     * 用户查询个人信息
     */
    @GetMapping("/lookMyUser")
    @ApiOperation("shlo:用户查询个人信息")
    public Result<UserStartVo> lookMyUser() {
        FwUser user = getUser();
        FwUser fwUser = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getId, user.getId()));
        //更新登录时间
        fwUser.setUpdateTime(LocalDateTime.now());
        userService.updateFwUser(fwUser);
        UserStartVo vo = new UserStartVo();
        BeanUtil.copyProperties(fwUser, vo);
        FwUljoin uljoin = uljoinService.getOne(Wrappers.<FwUljoin>lambdaQuery().eq(FwUljoin::getUserId, user.getId()).eq(FwUljoin::getIsUse, 1));
        if (uljoin == null) {
            vo.setUserStart("普通用户");
        } else {
            FwIdentity byId = identityService.getById(uljoin.getIdentityId());
            vo.setUserStart(byId.getIdentityName().concat("级用户"));
            vo.setShow(true);
        }

        return success(vo);
    }

    /**
     * shlo:
     * 完善/修改个人信息
     */
    @PutMapping("/updateUser")
    @ApiOperation("shlo:用户完善/修改个人信息")
    public synchronized Result<Object> updateUser(@RequestBody FwUser fwUser) {
        String id = getUser().getId();
        fwUser.setId(id);
        // 废弃
         if (!StringUtils.isBlank(fwUser.getAliPhone())){
             List<FwUser> list = userService.list(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getAliPhone, fwUser.getAliPhone()));
             if (!list.isEmpty())
                 return new Result().fail(0,"支付宝账号已被使用!");
         }
        //若变更支付宝收款账号
        FwUser oldUser = userService.getById(id);
        if ( (StringUtils.isNotEmpty(fwUser.getAliPhone()) && !fwUser.getAliPhone().equals(oldUser.getAliPhone())) ||
            StringUtils.isNotEmpty(fwUser.getPayPassWord()) ) {
            if (StringUtils.isEmpty(fwUser.getTwoPassWord())) {return new Result<>().fail(1,"请输入支付密码");}
            if (!fwUser.getTwoPassWord().equals(oldUser.getPayPassWord())) {
                return new Result<>().fail(2,"支付密码错误");
            }
        }

        //更新登录时间
        fwUser.setUpdateTime(LocalDateTime.now());
        if (fwUser.getParentId() != null) {
            userService.bindingParent(fwUser);
        }
        return success(userService.updateFwUser(fwUser));
    }

    /**
     * shlo:
     * 解绑设备信息信息
     */
    @GetMapping("/imeiNull/{phone}/{code}")
    @ApiOperation("shlo:解绑设备信息信息")
    public Result imeiNull(@PathVariable String phone, @PathVariable String code) {
        //验证验证码
        Integer flag = userService.checkCode(phone, code);
        if (flag == -1) {
            return new Result().fail(0, "请去获取验证码");
        }
        if (flag == 0) {
            return new Result().fail(0, "验证码错误");
        }
        FwUser user = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getPhone, phone));
        return success(userService.imeiNull(user));
    }


    /**
     * shlo: 发送验证码
     *
     * @param phone
     * @return
     * @ todo 正式上线后不送回code
     */
    @GetMapping("/sendPhone/{phone}")
    @ApiOperation("shlo:发送验证码")
    public Result sendPhone(@PathVariable String phone) {
        if (!Validator.isMobile(phone))
            return new Result(CodeStatus.ACCOUNT_FORMAT_ERROR);
        String code = RandomUtil.randomInt(6) + "" + RandomUtil.randomInt(6) + "" + RandomUtil.randomInt(6) + "" + RandomUtil.randomInt(6) + "" + RandomUtil.randomInt(6) + "" + RandomUtil.randomInt(6);
        Assert.isTrue(Objects.isNull(redisTemplate.opsForValue().get(phone)), "5分钟内不可再发送.");
        redisTemplate.opsForValue().set(phone, code, 5, TimeUnit.MINUTES);
        ChuangLanSmsUtil.sendSms(phone, code, "5");
        return success(code);
    }

    /**
     * shlo:
     *
     * @param phone
     * @param code
     * @return
     */
    @GetMapping("/isCheckCode")
    @ApiOperation("shlo:验证验证码 参数 phone code")
    public Result isCheckCode(@RequestParam String phone, @RequestParam String code) {
        Integer flag = userService.checkCode(phone, code);
        if (flag == -1)
            return new Result().fail(0, "请去获取验证码");
        if (flag == 0)
            return new Result().fail(0, "验证码错误");
        return success();
    }


    /**
     * shlo:
     * 手机号用户注册
     */
    @PutMapping("/userRegister")
    @ApiOperation("shlo:用户手机号注册,绑定设备号(App调)")
    @Transactional(rollbackFor = Exception.class)
    public Result userRegister(@RequestBody RegisterForm registerForm) {
        //验证验证码
        Integer flag = userService.checkCode(registerForm.getPhone(), registerForm.getCode());
        if (flag == -1) {
            return new Result().fail(0, "请去获取验证码");
        }
        if (flag == 0) {
            return new Result().fail(0, "验证码错误");
        }
        FwUser one = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getPhone, registerForm.getPhone()));
        if (one != null) {
            return new Result().fail(100, "该手机号已注册");
        }
        //获取上级数据
        FwUser parentUser = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getSystemHost, registerForm.getParentCode()));
        //验证用户使用的邀请码是否正确
        if (!registerForm.getParentCode().equals("") && parentUser == null) {
            return new Result().fail(101, "邀请码错误,请核实");
        }

        //初始化用户
        FwUser user = new FwUser()
                .setId(idXD.nextId())//用户编号
                .setUserName("用户")
                .setHeadImage("http://shangjia1.0.obs.cn-east-3.myhuaweicloud.com/608b7ad1ad374ad6ab32892a8dac06c5")//默认头像
                .setCreateTime(LocalDateTime.now())//创建时间
                .setPhone(registerForm.getPhone())//手机号
                .setPassWord("123456")//密码
                .setPayPassWord("123456")//支付密码
                .setIsWithdraw(1)//默认可提现
                .setDisappearIsMore(0)//默认不可多级得消证
                .setSystemHost(idXD.nextId());//用户编号(对甲方)
        //更新用户积分兑换比例
        //获取积分兑换比例
        FwRuleDatas datas = ruleDatasService.getOne(Wrappers.<FwRuleDatas>lambdaQuery().eq(FwRuleDatas::getId, Constant.IsRuleData.INTEGRAL_RELEASE));
        user.setToRelease(datas.getRuleCount());
        //若设备号不为空将其写入
        if (registerForm.getImei() != null) {
            user.setImei(registerForm.getImei());
        }

        if (registerForm.getParentCode() != null && !registerForm.getParentCode().equals("")) {
            user.setParentId(parentUser.getId());//若邀请码不为空,将其写入上级编号
            userService.insertFwUser(user);
            /** 绑定上级后续逻辑 */
            userService.bindingParent(user);
        } else {
            userService.insertFwUser(user);
        }

        /** 初始化钱包 */
        moneysService.save(new FwMoneys()
                .setId(idXD.nextId())
                .setUserId(user.getId())
                .setCreateTime(LocalDateTime.now())
                .setIntegral(new BigDecimal(0))
                .setDisappear(new BigDecimal(0))
                .setShangJia(new BigDecimal(0)));
        //送回token
        String json = JSON.toJSON(user).toString();
        String token = authUtils.createJWT(user.getId(), json, null);
        return success(token);
    }

    @Autowired
    private V2ReadPackageController readPackageController;
    /**
     * shlo:
     * 手机号用户注册
     */
    @PutMapping("/userRegisterH")
    @ApiOperation("shlo:用户手机号注册,绑定设备号(H5调)")
    @Transactional(rollbackFor = Exception.class)
    public Result userRegisterH(@RequestBody RegisterForm registerForm) {
        //验证验证码
        Integer flag = userService.checkCode(registerForm.getPhone(), registerForm.getCode());
        if (flag == -1) {
            return new Result().fail(0, "请去获取验证码");
        }
        if (flag == 0) {
            return new Result().fail(0, "验证码错误");
        }
        FwUser one = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getPhone, registerForm.getPhone()));
        if (one != null) {
            return new Result().fail(100, "该手机号已注册");
        }

        //验证用户使用的邀请码是否正确
        FwUser parentUser = null;
        if (registerForm.getParentCode() != null) {
            //获取其上级数据
             parentUser = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getSystemHost, registerForm.getParentCode()));
            if (parentUser == null) {
                return new Result().fail(101, "邀请码错误,请核实");
            }
        }

        //初始化用户
        FwUser user = new FwUser()
                .setId(idXD.nextId())//用户编号
                .setUserName("用户")
                .setHeadImage("http://shangjia1.0.obs.cn-east-3.myhuaweicloud.com/608b7ad1ad374ad6ab32892a8dac06c5")//默认头像
                .setCreateTime(LocalDateTime.now())//创建时间
                .setPhone(registerForm.getPhone())//手机号
                .setPassWord("123456")//密码
                .setPayPassWord("123456")//支付密码
                .setIsWithdraw(1)//默认可提现
                .setDisappearIsMore(0)//默认不可多级得消证
                .setSystemHost(idXD.nextId());//用户编号(对甲方)
        //更新用户积分兑换比例
        //获取积分兑换比例
        FwRuleDatas datas = ruleDatasService.getOne(Wrappers.<FwRuleDatas>lambdaQuery().eq(FwRuleDatas::getId, Constant.IsRuleData.INTEGRAL_RELEASE));
        user.setToRelease(datas.getRuleCount());
        if (Objects.nonNull(parentUser)) {
            user.setParentId(parentUser.getId());//若邀请码不为空,将其写入上级编号
            userService.insertFwUser(user);
            /** 绑定上级后续逻辑 */
            userService.bindingParent(user);
            //完成上级的邀请注册红包任务
            readPackageController.taskCommit("3",parentUser.getId());
        } else {
            userService.insertFwUser(user);
        }


        /** 初始化钱包 */
        moneysService.save(new FwMoneys()
                .setId(idXD.nextId())
                .setUserId(user.getId())
                .setCreateTime(LocalDateTime.now())
                .setIntegral(new BigDecimal(0))
                .setDisappear(new BigDecimal(0))
                .setShangJia(new BigDecimal(0)).setManShangjia(NumberUtil.add(0D)).setTecShangjia(NumberUtil.add(0D)));
        //送回token
        String json = JSON.toJSON(user).toString();
        String token = authUtils.createJWT(user.getId(), json, null);
        return success(token);
    }


    /**
     * shlo:
     * 用户查询我的商品收藏
     */
    @GetMapping("/lookMyCollect")
    @ApiOperation("shlo:用户查询我的商品收藏")
    public Result<List<UcjoinVo>> lookMyCollect() {
        FwUcjoin fwUcjoin = new FwUcjoin();
        fwUcjoin.setUserId(getUser().getId());
        List<UcjoinVo> ucjoinVos = ucjoinService.selectFwUcjoinList(fwUcjoin);
        return success(ucjoinVos);
    }


    /**
     * 添加/取消商品收藏
     * shlo:
     *
     * @param id
     * @return
     */
    @GetMapping("/collect/{id}")
    @ApiOperation("shlo:添加/取消商品收藏,传商品id")
    public Result collect(@PathVariable String id) {
        FwUser user = getUser();
        //获取需要操作的收藏数据
        FwUcjoin ucjoin = ucjoinService.getOne(Wrappers.<FwUcjoin>lambdaQuery().eq(FwUcjoin::getItemId, id).eq(FwUcjoin::getUserId, user.getId()));
        //判断该数据是否已存在
        if (ucjoin == null) {
            //不存在,添加数据
            FwUcjoin fwUcjoin = new FwUcjoin();
            fwUcjoin.setCreateBy(user.getUserName());
            fwUcjoin.setUserId(user.getId());
            fwUcjoin.setItemId(id);
            ucjoinService.insertFwUcjoin(fwUcjoin);
            return success("已添加收藏");
        } else {
            //存在,抹除数据
            ucjoinService.deleteFwUcjoinById(ucjoin.getId());
            return success("已取消收藏");
        }
    }


    /**
     * shlo:
     * 用户查询我的店铺收藏
     */
    @GetMapping("/lookMyShopCollect")
    @ApiOperation("shlo:用户查询我的店铺收藏")
    public Result<List<UsjoinVo>> lookMyShopCollect() {
        FwUsjoin fwUsjoin = new FwUsjoin();
        fwUsjoin.setUserId(getUser().getId());

        List<UsjoinVo> usjoinVos = usjoinService.selectFwUsjoinList(fwUsjoin);

        return success(usjoinVos);
    }


    /**
     * 添加/取消商品收藏
     * shlo:
     *
     * @param id
     * @return
     */
    @GetMapping("/collectShop/{id}")
    @ApiOperation("shlo:添加/取消商铺收藏,传商铺编号:shopId")
    public Result collectShop(@PathVariable String id) {
        FwUser user = getUser();
        //获取需要操作的收藏数据
        FwUsjoin usjoin = usjoinService.getOne(Wrappers.<FwUsjoin>lambdaQuery().eq(FwUsjoin::getUserId, user.getId()).eq(FwUsjoin::getShopId, id));
        //判断该数据是否已存在
        if (usjoin == null) {
            //不存在,添加数据
            FwUsjoin fwUsjoin = new FwUsjoin();
            fwUsjoin.setUserId(user.getId());
            fwUsjoin.setUpdateTime(LocalDateTime.now());
            fwUsjoin.setCreateBy(user.getUserName());
            fwUsjoin.setUpdateBy(user.getUserName());
            fwUsjoin.setShopId(id);
            usjoinService.insertFwUsjoin(fwUsjoin);
            return success("已添加收藏");
        } else {
            //存在,抹除数据
            usjoinService.deleteFwUsjoinById(usjoin.getId());
            return success("已取消收藏");
        }
    }

    /**
     * 我的:页面统计,消证,积分,收藏
     * shlo:
     *
     * @return
     */
    @GetMapping("/myCount")
    @ApiOperation("shlo:我的:页面统计,消证,积分,收藏")
    public Result<myCountVo> myCount() {
        myCountVo myCountVo = new myCountVo();
        FwUser user = getUser();
        //获取当前用户商品收藏数据
        List<FwUcjoin> ucjoins = ucjoinService.list(Wrappers.<FwUcjoin>lambdaQuery().eq(FwUcjoin::getUserId, user.getId()));
        //获取当前用户店铺收藏数据
        List<FwUsjoin> usjoins = usjoinService.list(Wrappers.<FwUsjoin>lambdaQuery().eq(FwUsjoin::getUserId, user.getId()));
        //获取用户钱包数据
        FwMoneys moneys = moneysService.getOne(Wrappers.<FwMoneys>lambdaQuery().eq(FwMoneys::getUserId, user.getId()));
        //充实vo
        myCountVo.setCollectCount(ucjoins.size());
        myCountVo.setShopCollectCount(usjoins.size());
        myCountVo.setDisappear(moneys.getDisappear());
        myCountVo.setIntegral(moneys.getIntegral());
        //送回数据
        return success(myCountVo);
    }

    /**
     * shlo:查询可购买代理身份
     *
     * @return
     */
    @GetMapping("/findShopIngRuleList")
    @ApiOperation("shlo:查询可购买代理身份,:")
    public Result findShopIngRuleList() {
        //初始化 查询条件
        String[] a = {Constant.Identity.AREA_VIP_ID, Constant.Identity.CITY_VIP_ID, Constant.Identity.PROVINCE_VIP_ID};
        //获取数据规则表数据
        List<FwRuleDatas> list = ruleDatasService.list(Wrappers.<FwRuleDatas>lambdaQuery().in(FwRuleDatas::getRuleType, a));
        //获取代理身份数据
        List<FwIdentity> identities = identityService.list(Wrappers.<FwIdentity>lambdaQuery().in(FwIdentity::getId, a));
        //获取当前用户的身份数据
        FwUser user = getUser();
        FwUljoin uljoin = uljoinService.getOne(Wrappers.<FwUljoin>lambdaQuery().eq(FwUljoin::getUserId, user.getId()).eq(FwUljoin::getIsUse, Constant.IsUsr.IS_USR));
        //创建用于送回的vo
        BuyIdentityAgencyVo buyIdentityAgencyVo = new BuyIdentityAgencyVo();
        if (uljoin != null) {
            String identityId = uljoin.getIdentityId();
            buyIdentityAgencyVo.setIdentity(identityId);
        }
        //创建vo集合.用于保存送回的vo数据
        ArrayList<IdentityAgencyVo> identityAgencyVos = new ArrayList<>();
        for (FwIdentity identity : identities) {
            for (FwRuleDatas fwRuleDatas : list) {
                if (identity.getId().equals(fwRuleDatas.getId())) {
                    IdentityAgencyVo identityAgencyVo = new IdentityAgencyVo();
                    /*identityAgencyVo.setIdentityInfo(identity.getIdentityInfo());
                    identityAgencyVo.setId(identity.getId());
                    identityAgencyVo.setIdentityName(identity.getIdentityName());*/
                    BeanUtil.copyProperties(identity, identityAgencyVo);
                    identityAgencyVo.setMoney(fwRuleDatas.getRuleCount());//充实金额
                    if (identityAgencyVo.getId().equals("5")) {
                        identityAgencyVo.setIsOpen("1");//设置开发
                    } else {
                        identityAgencyVo.setIsOpen("-1");//设置市级省级暂未开发
                    }
                    identityAgencyVos.add(identityAgencyVo);//写入集合
                }
            }
        }
        buyIdentityAgencyVo.setIdentityAgencyVos(identityAgencyVos);
        //送回数据
        return success(buyIdentityAgencyVo);
    }


    /**
     * shlo:购买代理
     */
    @PostMapping("/ShopIngRule")
    @ApiOperation("shlo:购买代理身份")
    @PrintParam
    public Result ShopIngRule(@RequestBody ShopIngAgencyForm shopIngAgencyForm) {

        //判断代理区域是否有人已经购买过了
        //判断用户是不是已经是代理了
        List<FwUljoin> list = uljoinService.list(Wrappers.<FwUljoin>lambdaQuery().eq(FwUljoin::getIsUse, 1).eq(FwUljoin::getUserId, this.getUser().getId())
                .eq(FwUljoin::getSysCode,5).or(true).eq(FwUljoin::getSysCode,6).or(true).eq(FwUljoin::getSysCode,7));
        if (list.size() > 0)
            return new Result().fail(0,"您已经是代理了");
        FwAgentRegion region = new FwAgentRegion();
        if (shopIngAgencyForm.getId().equals("5")) {
            //区县
            region = agentRegionService.getOne(Wrappers.<FwAgentRegion>lambdaQuery().eq(FwAgentRegion::getProvince, shopIngAgencyForm.getProvince())
                    .eq(FwAgentRegion::getCity, shopIngAgencyForm.getCity()).eq(FwAgentRegion::getArea, shopIngAgencyForm.getArea()));
        } else if (shopIngAgencyForm.getId().equals("6")) {
            //市级
            region = agentRegionService.getOne(Wrappers.<FwAgentRegion>lambdaQuery().eq(FwAgentRegion::getProvince, shopIngAgencyForm.getProvince())
                    .eq(FwAgentRegion::getCity, shopIngAgencyForm.getCity()));

        } else if (shopIngAgencyForm.getId().equals("7")) {
            //省级
            region = agentRegionService.getOne(Wrappers.<FwAgentRegion>lambdaQuery().eq(FwAgentRegion::getProvince, shopIngAgencyForm.getProvince()));
        }
        if (region != null) {
            return new Result<>().fail(0, "您选择的代理区域已被别人购买");
        }


        /**
         * 发起支付
         */
        FwUser user = getUser();
        shopIngAgencyForm.setUserId(user.getId());
        String s;
        //TODO 代理实际金额，避免web攻击
        // FwRuleDatas datasService = ruleDatasService.getOne(Wrappers.<FwRuleDatas>lambdaQuery().eq(FwRuleDatas::getId, shopIngAgencyForm.getId()));
        // 验证该区域是否有相同代理 根据省 ，市 ，区 这三个不同的 ID项，去识别占用率。
        try {
            s = aliComm.appPay(UUID.randomUUID().toString().replace("-", ""),//阿里订单编号,传日志id
                    shopIngAgencyForm.getMoney(),//支付金额
                    AliPayEnum.agency_pay,//支付回调
                    JSON.toJSONString(shopIngAgencyForm)
            );
            //TODO 有点危险
            FwUser fwUser = userService.selectFwUserById(user.getId());
            //identityService.addIdentity(fwUser);
        } catch (AlipayApiException e) {
            return success().fail(-1, "支付失败");
        }

        return success(s);
    }


    @GetMapping("/agentDetail")
    @ApiOperation("shlo:代理管理-收益明细")
    public Result agentDetail() {
        //创建vo对象
        AgentDetailVo agentDetailVo = new AgentDetailVo();
        //获取当前登录者信息
        FwUser user = getUser();
        //获取代理区域数据
        FwAgentRegion agentRegion = agentRegionService.getOne(Wrappers.<FwAgentRegion>lambdaQuery().eq(FwAgentRegion::getUserId, user.getId()).eq(FwAgentRegion::getIsDefault, Constant.AddrIsDefault.IS_DEFAULT_YES));
        //充实vo
        agentDetailVo.setArea(districtService.codeConversionName(agentRegion.getArea()));
        agentDetailVo.setCity(districtService.codeConversionName(agentRegion.getCity()));
        agentDetailVo.setProvince(districtService.codeConversionName(agentRegion.getProvince()));
        //获取消证收入,消证余额
        FwMoneys moneys = moneysService.getOne(Wrappers.<FwMoneys>lambdaQuery().eq(FwMoneys::getUserId, user.getId()));
        BigDecimal disappear = moneys.getDisappear();
        //充实vo
        agentDetailVo.setDisappear(disappear);
        //获取消证收入明细
        List<FwLogs> logsList = logsService.list(Wrappers.<FwLogs>lambdaQuery()
                .eq(FwLogs::getModelName, LogsModelEnum.DISAPPEAR_MODEL.getModelName())//查消证模块
                .eq(FwLogs::getIsType, LogsTypeEnum.MONEY_INCOME.getTypeName())//查收入
        );
        //充实vo
        agentDetailVo.setFwLogs(logsList);
        //送回vo数据
        return success(agentDetailVo);
    }

    /**
     * 支付宝登录
     */
    @GetMapping("/userAliCode/{aliCode}/{imei}")
    @ApiOperation("支付宝授权code")
    public Result aliLogin(@PathVariable String aliCode, @PathVariable String imei) {
        AliLoginVo aliLoginVo = new AliLoginVo();
        AliAppUserAccToken aliAppUserAccToken = null;
        String token = null;
        String isNew = "0";
        try {
            aliAppUserAccToken = aliComm.aliAppLogin(aliCode);
            AliAppUserInfo aliUserInfo = aliComm.getAliUserInfo(aliAppUserAccToken.getAccessToken());
            FwUser user = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getAppAuthToken, aliUserInfo.getUserId()));
            if (Objects.nonNull(user)) {
                // 如果是老用户,
                if (user.getImei() != null && !imei.equals(user.getImei()) && !user.getImei().equals("")) {
                    token = "-999";
                    aliLoginVo.setAliCode(aliCode);
                    aliLoginVo.setIsNew(isNew);
                    aliLoginVo.setToken(token);
                    aliLoginVo.setPhone(user.getPhone());
                    return success(aliLoginVo);
                }
                user.setImei(imei);
                user.setUpdateTime(LocalDateTime.now());
                userService.updateFwUser(user);
                //写入token
                String json = JSON.toJSON(user).toString();
                token = authUtils.createJWT(user.getId(), json, null);
            } else {
                //如果是新用户
                isNew = "1";
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        aliLoginVo.setIsNew(isNew);
        aliLoginVo.setToken(token);
        aliLoginVo.setAliCode(aliCode);
        return success(aliLoginVo);
    }

    /**
     * shlo:
     * 支付宝用户注册完善信息
     */
    @PutMapping("/aliRegisterLogin")
    @ApiOperation("shlo:支付宝用户注册完善信息)")
    @Transactional(rollbackFor = Exception.class)
    public Result aliRegisterLogin(@RequestBody AliRegisterForm aliRegisterForm) {
        //验证验证码
        Integer flag = userService.checkCode(aliRegisterForm.getPhone(), aliRegisterForm.getCode());
        if (flag == -1) {
            return new Result().fail(101, "请去获取验证码");
        }
        if (flag == 0) {
            return new Result().fail(101, "验证码错误");
        }

        //验证用户使用的邀请码是否正确
        if (aliRegisterForm.getParentCode() != null && !aliRegisterForm.getParentCode().equals("")) {
            //获取其上级数据
            FwUser parentUser = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getSystemHost, aliRegisterForm.getParentCode()));
            if (parentUser == null) {
                return new Result().fail(101, "邀请码错误,请核实");
            }
        }
        AliAppUserAccToken aliAppUserAccToken = null;
        //初始化用户
        FwUser user = new FwUser();
        try {
            aliAppUserAccToken = aliComm.aliAppLogin(aliRegisterForm.getAliCode());
            AliAppUserInfo aliUserInfo = aliComm.getAliUserInfo(aliAppUserAccToken.getAccessToken());
            //判断该手机号是否已经注册
            FwUser one = userService.getOne(Wrappers.<FwUser>lambdaQuery().eq(FwUser::getPhone, aliRegisterForm.getPhone()));
            //判断手机号是否已注册
            if (one != null) {
                //判断该手机注册的账号是否已绑定了支付宝
                if (one.getAppAuthToken() != null) {
                    //若已绑定
                    return new Result().fail(100, "该手机号注册的账号已绑定了其他支付宝账号");
                } else {
                    //若未绑定,直接将已经注册的账号绑定当前支付宝
                    one.setAppAuthToken(aliUserInfo.getUserId());
                    userService.updateFwUser(one);
                    //送回token
                    String json = JSON.toJSON(one).toString();
                    String token = authUtils.createJWT(one.getId(), json, null);
                    return success(token);
                }
            }

            //完善用户信息
            user.setAppAuthToken(aliUserInfo.getUserId());//支付宝唯一标识
            user.setId(idXD.nextId());//用户编号
            user.setUserName("商甲用户");//默认昵称
            user.setHeadImage("http://shangjia1.0.obs.cn-east-3.myhuaweicloud.com/608b7ad1ad374ad6ab32892a8dac06c5");//默认头像
            user.setCreateTime(LocalDateTime.now());//创建时间
            user.setPhone(aliRegisterForm.getPhone());//手机号
            user.setPassWord("123456");//密码
            user.setPayPassWord("123456");//支付密码
            user.setIsWithdraw(1);//默认可提现
            user.setDisappearIsMore(0);//默认不可多级得消证
            user.setSystemHost(idXD.nextId());//用户编号(对甲方)
            //更新用户积分兑换比例
            //获取积分兑换比例
            FwRuleDatas datas = ruleDatasService.getOne(Wrappers.<FwRuleDatas>lambdaQuery().eq(FwRuleDatas::getId, Constant.IsRuleData.INTEGRAL_RELEASE));
            user.setToRelease(datas.getRuleCount());

            if (aliRegisterForm.getParentCode() != null && !aliRegisterForm.getParentCode().equals("")) {
                user.setParentId(aliRegisterForm.getParentCode());//若邀请码不为空,将其写入上级编号
                userService.insertFwUser(user);
                /** 绑定上级后续逻辑 */
                userService.bindingParent(user);
            } else {
                userService.insertFwUser(user);
            }

            /** 初始化钱包 */
            moneysService.save(new FwMoneys()
                    .setId(idXD.nextId())
                    .setUserId(user.getId())
                    .setCreateTime(LocalDateTime.now())
                    .setIntegral(new BigDecimal(0))
                    .setDisappear(new BigDecimal(0))
                    .setShangJia(new BigDecimal(0)));
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //送回token
        String json = JSON.toJSON(user).toString();
        String token = authUtils.createJWT(user.getId(), json, null);
        return success(token);
    }


    /**
     * 支付宝吊起加密 RSA2
     */

    @SneakyThrows
    @GetMapping("/pushSign")
    @ApiOperation("加密后 送回sign")
    public Result pushSign() {
        String sign = "apiname=com.alipay.account.auth&app_id=2021002148691547&app_name=mc&auth_type=AUTHACCOUNT&biz_type=openservice&method=alipay.open.auth.sdk.code.get&pid=2088721526050792&product_id=APP_FAST_LOGIN&scope=kuaijie&sign_type=RSA2&target_id=" + DateUtil.date().getTime();
        return success(sign + "&sign=" + AlipaySignature.rsaSign(sign, aliComm.getAliConfig().getPrivateKey(), "utf-8", "RSA2"));
    }


    //检测用户是否完善用户信息
    @GetMapping("/checkUserInfo")
    @ApiOperation("检测用户是否完善用户信息")
    public Result checkUserInfo() {

        FwUser user = this.getUser();
        FwAddrs addrs = addrsService.getOne(Wrappers.<FwAddrs>lambdaQuery().eq(FwAddrs::getUserId, user.getId()));
        if (StringUtils.isBlank(user.getUserName()) || StringUtils.isBlank(user.getPhone()) || StringUtils.isBlank(user.getHeadImage()) || StringUtils.isBlank(user.getAliPhone()) || null == addrs)
            return success(2);
        return success(1);
    }

    @GetMapping("/getShareUrl")
    @ApiOperation("分享APP地址")
    public Result<Object> getShareUrl(){
        String  shareUtl = Constant.ShareUrl.APP_DESC_URL+ "?invitationCode=" + getUser().getSystemHost();
        return success(shareUtl);
    }

    // 绑定支付宝
    @SneakyThrows
    @PostMapping("/ali/preconsult")
    @ApiOperation("实名证件信息比对验证预咨询,返回 verify_id,前端保存即可")
    public Result<String> preconsult(@Validated @RequestBody AliBindForm aliBindForm){
        String verifyId = aliComm.getVerifyId(JSON.parseObject(JSON.toJSONString(aliBindForm)).getInnerMap());
        // 用户信息余先保存
        return success(verifyId);
    }

    // 根据 code 获取 token
    @SneakyThrows
    @GetMapping("/ali/getToken/{code}")
    @ApiOperation("根据 code 获取 token,返回 token ,前端保存即可")
    public Result<String> getToken(@PathVariable String code){
        AliAppUserAccToken aliAppUserAccToken = aliComm.aliAppLogin(code);
        return success(aliAppUserAccToken.getAccessToken());
    }

    // 根据 token 和  verifyId 去检验是否正确
    @SneakyThrows
    @PostMapping("/ali/consult")
    @ApiOperation("根据 token 和  verifyId 去检验是否正确")
    public Result<AliBindResultVo> consult(@Validated @RequestBody AliBindCheckForm aliBindCheckForm){
        AlipayUserCertdocCertverifyConsultResponse consult = aliComm.consult(aliBindCheckForm.getToken(), aliBindCheckForm.getVerifyId());
        AliBindResultVo aliBindResultVo = new AliBindResultVo();
        aliBindResultVo.setPassed(consult.getPassed());
        aliBindResultVo.setFail_reason(consult.getFailReason());
        return success(aliBindResultVo);

    }



}

